<?php

namespace App\Http\Controllers;

use App\Exceptions\CouponCodeUnavailableException;
use App\Models\CouponCode;
use Carbon\Carbon;
use App\Models\Order;
use App\Jobs\CloseOrder;
use App\Models\ProductSku;
use App\Models\UserAddress;
use App\Events\OrderReviewd;
use Illuminate\Http\Request;
use App\Services\CartService;
use App\Services\OrderService;
use App\Http\Requests\OrderRequest;
use App\Http\Requests\SendReviewRequest;
use App\Http\Requests\ApplyRefundRequest;
use App\Exceptions\InvalidRequestException;

class OrdersController extends Controller
{

    // 订单列表
    public function index(Request $request) {
        $orders = Order::query()
                // 使用 with 方法预加载，避免 N+1 问题
                ->with(['items.product','items.productSku'])
                ->where('user_id',$request->user()->id)
                ->orderBy('created_at','desc')
                ->paginate();

        return view('orders.index',['orders' => $orders]);
    }

    // 订单详情页面
    public function show(Order $order,Request $request) {
        $this->authorize('own',$order);

        return view('orders.show', ['order' => $order->load(['items.productSku', 'items.product'])]);
    }
    // 提交订单
    public function store(OrderRequest $request, OrderService $orderService){
        $user    = $request->user();
        $address = UserAddress::find($request->input('address_id'));
        $coupon = null;
        // 如果用户提交了优惠码
        if($code = $request->input('coupon_code')) {
            $coupon = CouponCode::where('code',$code)->first();
            if (!$coupon) {
                throw new CouponCodeUnavailableException('优惠券不存在');
            }
        }
        return $orderService->store($user, $address, $request->input('remark'), $request->input('items'),$coupon);
    }

    // 提交订单---初始
    public function store_init(OrderRequest $request,CartService $cartService) {
        $user = $request->user();

        // 开启一个数据库事务
        $order = \DB::transaction(function() use($user,$request,$cartService) {
            $address = UserAddress::find($request->input('address_id'));
            // 更新此地址的最后使用时间
            $address->update(['last_used_at' => Carbon::now()->toDateTimeString()]);
            // 创建一个订单
            $order = new Order([
                'address' => [
                    'address' => $address->full_address,
                    'zip' => $address->zip,
                    'contact_name' => $address->contact_name,
                    'contact_phone' => $address->contact_phone,
                ],
                'remark' => $request->input('remark'),
                'total_amount' => 0,
            ]);
            // 订单关联到当前用户
            $order->user()->associate($user);
            // 写入数据库
            $order->save();
            $totalAmount = 0;
            $items = $request->input('items');
            // 遍历用户提交的sku
            foreach($items as $data) {
                $sku = ProductSku::find($data['sku_id']);
                // 创建一个 OrderItem 并直接与当前订单关联
                $item = $order->items()->make([
                    'amount' => $data['amount'],
                    'price' => $sku->price,
                ]);
                $item->product()->associate($sku->product_id);
                $item->productSku()->associate($sku);
                $item->save();
                $totalAmount += $sku->price * $data['amount'];
                if($sku->decreaseStock($data['amount']) <= 0) {
                    throw new InvalidRequestException('该商品库存不足');
                }
            }
            // 更新订单总金额
            $order->update(['total_amount' => $totalAmount]);

            // 将下单的商品从购物车中移除
            /*
            $skuIds = collect($request->input('items'))->pluck('sku_id');
            $user->cartItems()->whereIn('product_sku_id',$skuIds)->delete();
            */
            $skuIds = collect($request->input('items'))->pluck('sku_id')->all();
            $cartService->remove($skuIds);
            return $order;
        });
        // 使用队列
        $this->dispatch(new CloseOrder($order,config('app.order_ttl')));

        return $order;
    }

    // 确认收货
    public function received(Order $order,Request $request) {
        // 校验权限
        $this->authorize('own',$order);
        // 判断订单的发货状态是否为已发货
        if($order->ship_status !== Order::SHIP_STATUS_DELIVERED) {
            throw new InvalidRequestException('发货状态不正确');
        }
        // 更新发货状态为已收到
        $order->update([
            'ship_status' => Order::SHIP_STATUS_RECEIVED
        ]);

        // 返回订单信息
        return $order;
    }

    // 评价订单
    public function review(Order $order) {
        // 校验权限
        $this->authorize('own',$order);
        // 判断是否 已经支付
        if(!$order->paid_at) {
            throw new InvalidRequestException('该订单未支付，不可评价');
        }
        // 使用load 方法加载关联数据，避免 N+1 性能问题
        return view('orders.review',['order' => $order->load(['items.productSku','items.product'])]);
    }

    // 发送评价
    public function sendReview(Order $order, SendReviewRequest $request) {
        // 校验权限
        $this->authorize('own',$order);

        if(!$order->paid_at) {
            throw new InvalidRequestException('该订单未支付，不可评价');
        }
        // 判断是否已经评价
        if($order->reviewed) {
            throw new InvalidRequestException('该订单已评价，不可重复提交');
        }
        $reviews = $request->input('reviews');
        // 开启事务
        \DB::transaction(function() use($reviews,$order) {
            // 遍历用户提交的数据
            foreach($reviews as $review) {

                $orderItem = $order->items()->find($review['id']);
                // 保存评分和评价
                $orderItem->update([
                    'rating'        => $review['rating'],
                    'review'        => $review['review'],
                    'reviewd_at'    => Carbon::now(),
                ]);
            }
            // 将订单标记为已评价
            $order->update(['reviewed' => true]);
            event(new OrderReviewd($order));
        });

        return redirect()->back();
    }

    // 申请退款
    public function applyRefund(Order $order,ApplyRefundRequest $request) {
        // 校验订单是否属于当前用户
        $this->authorize('own',$order);
        // 判断订单是否已付款
        if(!$order->paid_at) {
            throw new InvalidRequestException('该订单未支付，不可退款');
        }
        // 判断订单退款状态是否正确
        if($order->refund_status !== Order::REFUND_STATUS_PENDING) {
            throw new InvalidRequestException('该订单已经申请过退款，请勿重复申请');
        }

        // 将用户输入的退款理由放到订单的extra 字段中
        $extra = $order->extra ? : [];
        $extra['refund_reason'] = $request->input('reason');

        // 将订单退款状态改为已申请退款
        $order->update([
            'refund_status' => Order::REFUND_STATUS_APPLIED,
            'extra'         => $extra,
        ]);
        return $order;
    }

}
